{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Using a Multiple Layer Network\n",
    "\n",
    "\n",
    "We will illustrate how to use a Multiple Layer Network in TensorFlow\n",
    "\n",
    "### Low Birthrate data:\n",
    "```\n",
    "#Columns    Variable                                      Abbreviation\n",
    "#---------------------------------------------------------------------\n",
    "# Low Birth Weight (0 = Birth Weight >= 2500g,            LOW\n",
    "#                          1 = Birth Weight < 2500g)\n",
    "# Age of the Mother in Years                              AGE\n",
    "# Weight in Pounds at the Last Menstrual Period           LWT\n",
    "# Race (1 = White, 2 = Black, 3 = Other)                  RACE\n",
    "# Smoking Status During Pregnancy (1 = Yes, 0 = No)       SMOKE\n",
    "# History of Premature Labor (0 = None  1 = One, etc.)    PTL\n",
    "# History of Hypertension (1 = Yes, 0 = No)               HT\n",
    "# Presence of Uterine Irritability (1 = Yes, 0 = No)      UI\n",
    "# Birth Weight in Grams                                   BWT\n",
    "#---------------------------------------------------------------------\n",
    "```\n",
    "The multiple neural network layer we will create will be composed of three fully connected hidden layers, with node sizes 50, 25, and 5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "import matplotlib.pyplot as plt\n",
    "import csv\n",
    "import os\n",
    "import os.path\n",
    "import random\n",
    "import numpy as np\n",
    "import random\n",
    "import requests\n",
    "from tensorflow.python.framework import ops"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Obtain the data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# name of data file\n",
    "birth_weight_file = 'birth_weight.csv'\n",
    "\n",
    "# download data and create data file if file does not exist in current directory\n",
    "if not os.path.exists(birth_weight_file):\n",
    "    birthdata_url = 'https://github.com/nfmcclure/tensorflow_cookbook/raw/master/01_Introduction/07_Working_with_Data_Sources/birthweight_data/birthweight.dat'\n",
    "    birth_file = requests.get(birthdata_url)\n",
    "    birth_data = birth_file.text.split('\\r\\n')\n",
    "    birth_header = birth_data[0].split('\\t')\n",
    "    birth_data = [[float(x) for x in y.split('\\t') if len(x)>=1] for y in birth_data[1:] if len(y)>=1]\n",
    "    with open(birth_weight_file, \"w\") as f:\n",
    "        writer = csv.writer(f)\n",
    "        writer.writerows([birth_header])\n",
    "        writer.writerows(birth_data)\n",
    "        f.close()\n",
    "\n",
    "# read birth weight data into memory\n",
    "birth_data = []\n",
    "with open(birth_weight_file, newline='') as csvfile:\n",
    "    csv_reader = csv.reader(csvfile)\n",
    "    birth_header = next(csv_reader)\n",
    "    for row in csv_reader:\n",
    "        birth_data.append(row)\n",
    "\n",
    "birth_data = [[float(x) for x in row] for row in birth_data]\n",
    "\n",
    "\n",
    "# Extract y-target (birth weight)\n",
    "y_vals = np.array([x[8] for x in birth_data])\n",
    "\n",
    "# Filter for features of interest\n",
    "cols_of_interest = ['AGE', 'LWT', 'RACE', 'SMOKE', 'PTL', 'HT', 'UI']\n",
    "x_vals = np.array([[x[ix] for ix, feature in enumerate(birth_header) if feature in cols_of_interest] for x in birth_data])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Train model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Generation: 25. Loss = 5622.84\n",
      "Generation: 50. Loss = 2633.47\n",
      "Generation: 75. Loss = 2492.91\n",
      "Generation: 100. Loss = 2275.7\n",
      "Generation: 125. Loss = 2089.15\n",
      "Generation: 150. Loss = 2178.22\n",
      "Generation: 175. Loss = 2027.27\n",
      "Generation: 200. Loss = 2271.15\n"
     ]
    }
   ],
   "source": [
    "# reset the graph for new run\n",
    "ops.reset_default_graph()\n",
    "\n",
    "# Create graph session \n",
    "sess = tf.Session()\n",
    "\n",
    "# set batch size for training\n",
    "batch_size = 100\n",
    "\n",
    "# make results reproducible\n",
    "seed = 3\n",
    "np.random.seed(seed)\n",
    "tf.set_random_seed(seed)\n",
    "\n",
    "# Split data into train/test = 80%/20%\n",
    "train_indices = np.random.choice(len(x_vals), round(len(x_vals)*0.8), replace=False)\n",
    "test_indices = np.array(list(set(range(len(x_vals))) - set(train_indices)))\n",
    "x_vals_train = x_vals[train_indices]\n",
    "x_vals_test = x_vals[test_indices]\n",
    "y_vals_train = y_vals[train_indices]\n",
    "y_vals_test = y_vals[test_indices]\n",
    "\n",
    "\n",
    "# Normalize by column (min-max norm to be between 0 and 1)\n",
    "def normalize_cols(m):\n",
    "    col_max = m.max(axis=0)\n",
    "    col_min = m.min(axis=0)\n",
    "    return (m-col_min) / (col_max - col_min)\n",
    "    \n",
    "x_vals_train = np.nan_to_num(normalize_cols(x_vals_train))\n",
    "x_vals_test = np.nan_to_num(normalize_cols(x_vals_test))\n",
    "\n",
    "\n",
    "# Define Variable Functions (weights and bias)\n",
    "def init_weight(shape, st_dev):\n",
    "    weight = tf.Variable(tf.random_normal(shape, stddev=st_dev))\n",
    "    return(weight)\n",
    "    \n",
    "\n",
    "def init_bias(shape, st_dev):\n",
    "    bias = tf.Variable(tf.random_normal(shape, stddev=st_dev))\n",
    "    return(bias)\n",
    "    \n",
    "    \n",
    "# Create Placeholders\n",
    "x_data = tf.placeholder(shape=[None, 7], dtype=tf.float32)\n",
    "y_target = tf.placeholder(shape=[None, 1], dtype=tf.float32)\n",
    "\n",
    "\n",
    "# Create a fully connected layer:\n",
    "def fully_connected(input_layer, weights, biases):\n",
    "    layer = tf.add(tf.matmul(input_layer, weights), biases)\n",
    "    return(tf.nn.relu(layer))\n",
    "\n",
    "\n",
    "#--------Create the first layer (50 hidden nodes)--------\n",
    "weight_1 = init_weight(shape=[7, 25], st_dev=10.0)\n",
    "bias_1 = init_bias(shape=[25], st_dev=10.0)\n",
    "layer_1 = fully_connected(x_data, weight_1, bias_1)\n",
    "\n",
    "#--------Create second layer (25 hidden nodes)--------\n",
    "weight_2 = init_weight(shape=[25, 10], st_dev=10.0)\n",
    "bias_2 = init_bias(shape=[10], st_dev=10.0)\n",
    "layer_2 = fully_connected(layer_1, weight_2, bias_2)\n",
    "\n",
    "\n",
    "#--------Create third layer (5 hidden nodes)--------\n",
    "weight_3 = init_weight(shape=[10, 3], st_dev=10.0)\n",
    "bias_3 = init_bias(shape=[3], st_dev=10.0)\n",
    "layer_3 = fully_connected(layer_2, weight_3, bias_3)\n",
    "\n",
    "\n",
    "#--------Create output layer (1 output value)--------\n",
    "weight_4 = init_weight(shape=[3, 1], st_dev=10.0)\n",
    "bias_4 = init_bias(shape=[1], st_dev=10.0)\n",
    "final_output = fully_connected(layer_3, weight_4, bias_4)\n",
    "\n",
    "# Declare loss function (L1)\n",
    "loss = tf.reduce_mean(tf.abs(y_target - final_output))\n",
    "\n",
    "# Declare optimizer\n",
    "my_opt = tf.train.AdamOptimizer(0.05)\n",
    "train_step = my_opt.minimize(loss)\n",
    "\n",
    "# Initialize Variables\n",
    "init = tf.global_variables_initializer()\n",
    "sess.run(init)\n",
    "\n",
    "# Training loop\n",
    "loss_vec = []\n",
    "test_loss = []\n",
    "for i in range(200):\n",
    "    rand_index = np.random.choice(len(x_vals_train), size=batch_size)\n",
    "    rand_x = x_vals_train[rand_index]\n",
    "    rand_y = np.transpose([y_vals_train[rand_index]])\n",
    "    sess.run(train_step, feed_dict={x_data: rand_x, y_target: rand_y})\n",
    "\n",
    "    temp_loss = sess.run(loss, feed_dict={x_data: rand_x, y_target: rand_y})\n",
    "    loss_vec.append(temp_loss)\n",
    "    \n",
    "    test_temp_loss = sess.run(loss, feed_dict={x_data: x_vals_test, y_target: np.transpose([y_vals_test])})\n",
    "    test_loss.append(test_temp_loss)\n",
    "    if (i+1) % 25 == 0:\n",
    "        print('Generation: ' + str(i+1) + '. Loss = ' + str(temp_loss))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAZUAAAEWCAYAAACufwpNAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzs3Xl4FFXW+PHvSZMNQggkAYEAYZMdAkRAREBwQ0XQQQc3\nXFDcxpFxG9QZR/FlXnF+iqKiIouAzACCIiMi7voqAgYMRPYgoAkIJEAChC3J+f1RldgJCSSQTmc5\nn+fppyu36ladqkCf3Hur64qqYowxxpSFAH8HYIwxpuqwpGKMMabMWFIxxhhTZiypGGOMKTOWVIwx\nxpQZSyrGGGPKjCUVU6WISLSIbBSR0HI85gMiMr68jlcViciFIrLJ33GYs2dJxZQ5EdkuIhf76fBj\ngLdV9Ygby1cioiLSxXsjEXnfLe/v/hwhItNE5DcROSgim0VkjNf2KiKHReSQ1+sxd/VbwE0iUr98\nTvFkIhIkIk+JyCY3zlQRWSIil/orplNxr2ervJ9V9f9UtY0/YzJlw5KKqTJEJBi4FXin0KrNwAiv\n7SKB84G9XttMAMKAdkAd4GogudB+uqhqmNfreQBVPQos8T6Gr4hIjWJWzQeGuDHUBZoDLwNX+jqm\nwk4Ro6kGLKmYciUid4lIsojsE5FFItLILRcRmSAie0QkU0SSRKSju+4KEVnvtiBSReSRYnbfEzig\nqimFymcDfxQRj/vzDcD7wHGvbc4D/q2q+1U1V1U3qur8UpzaV5ziA9z9y/zPIvKziKSJyL9EJMBr\n/R0iskFE9ovIUhFpVqju/SKyBdhSxL4vBi4BhqjqClU97r4+VtUHvbZrJCILRGSviGwTkT97rXta\nROaJyEz3Oq8TkfhS1J0vIu+ISCZwm4j0EJHvReSAiOwSkVdFJMjd/hu36hq3xfdHEekvIile+2zn\ntjIPuLFc7bXubRF5TUQWu7GuEJGWp/0NmXJhScWUGxEZAPwvcD3QENgBzHFXXwr0Bc7FaSlcD6S7\n66YCd6tqbaAj8EUxh+gEFNUvvxNY7x4DnL/mZxbaZjkwTkRuF5HWpTszADYAXU6zzTVAPNANp1Vx\nB4CIDAGeAK4FooH/A/5TqO5QnKTZvoj9XgysKCKZ5nMT2H+BNUBjYCAwWkQu89rsapzfRwSwCHi1\nFHWH4LSWInCSeA7wFyAKp1U4ELgPQFX7unXyWn5zC8Ua6B7vE6A+8AAwW0S8u8eGA8/gtMqSgXHF\nnbspX5ZUTHm6CZimqqtV9RjwOHC+iMQCJ4DaQFtAVHWDqu5y650A2otIuNuSWF3M/iOAg8WsmwmM\nEJG2QISqfl9o/QM4H4Z/Ata7ralBhbZZ7f7lnPfy/lA9iJMMT2W8qu5T1V+Al3BaTAD3AP/rnnM2\n8E8gzru14q7flzdWVEgU8FveDyJSz40vQ0SOusXnAdGqOtZtxfyMMxY03Gs/36rqR6qaA8zi9yRZ\nkrrfq+pCt5V3RFVXqepyVc1W1e3Am0C/01yfPL1wuiKfc4/3BfCh1/UCeF9VV7rXazYQV8J9Gx+z\npGLKUyOc1gkAqnoIpzXS2P3geBV4DdgjIpNFJNzd9A/AFcAOEflaRM4vZv/7cRJTUd4DBuAkjVmF\nV7ofhP9U1e5AJDAPeFdE6nlt1k1VI7xeS73W1QYyTnn28KvX8g6c6wHQDHg5L1kB+wDBaRUUVbew\ndJyWX9657FPVCKA7EOx1jEbeSRGnddTAaz+/eS1nASHu+EhJ6haIT0TOFZEPxbnxIRMnUUad4hy8\nNQJ+VdVcr7IdFLwehWMNK+G+jY9ZUjHlaSfOBxQAIlIL5wM8FUBVJ7of6u1xusEedct/UNUhOF0h\nC3E+8Iuy1q13ElXNwhlMv5cikkqhbfM+BGvhDHiXRDuc7qFTaeK13BTneoDzgXx3oYQVqqrLvMM6\nxX4/B84TkZhTbPMrsK3QMWqr6hWnibmkdQvH9zqwEWitquE4SUhKcCxwrksT7zEnnOuVWsL6xo8s\nqRhfCRSREK9XDZxxgttFJE6cO7X+iTMWsF1EzhORnm5/+mHgKJArzq2yN4lIHVU9AWQCucUccyUQ\nISKNi1n/BNDP7Y4pQET+7sYQJCIhwIPAAYoeoylKP5ykdSqPikhdEWni7j9vLOEN4HER6eDGUkdE\nrivhcVHVT4AvgYXuNQxyr2Mvr81WAgdF5K8iEioiHhHpKCLnleAQZ1K3Ns7v6pDb5XhvofW7gRbF\n1F2B0/p4TEQCxbntezC/j7+ZCsySivGVj4AjXq+nVfUz4O/AAmAX0JLf++XDcfrp9+N0daQD/3LX\n3QJsd7tR7sEZmzmJqh4H3gZuLmb9TlX9tph4FZgOpOH8pXwJcKXbRZcn726lvNdLAG4SugKYUezV\ncHwArAISgcU4NyCgqu8D44E57jn+BBQezzmda3DGHd7BSYbbcK7TZe4xcoCrcMYetrnnOYXTjwOd\nad1HgBtxxpre4vcEmudpYIbbnXZ9oeMdx0kig9xjTQJGqOrG08Vq/E9ski5TlYhI3t1TXYsZ1PbF\nMR8AmqjqY6fYRnG6ggp/98WYKsWSijHlwJKKqS6s+8sYY0yZsZaKMcaYMmMtFWOMMWWm2j34LSoq\nSmNjY/0dhjHGVCqrVq1KU9Xo021X7ZJKbGwsCQkJ/g7DGGMqFRHZcfqtrPvLGGNMGbKkYowxpsxY\nUjHGGFNmqt2YijGmajhx4gQpKSkcPXr09BubEgsJCSEmJobAwMAzqm9JxRhTKaWkpFC7dm1iY2MR\nKekDkM2pqCrp6emkpKTQvHlJH9BdkHV/GWMqpaNHjxIZGWkJpQyJCJGRkWfV+rOkYoyptCyhlL2z\nvaaWVEro22+/ZcyYMdhjbYwxpniWVEpo9erVjB8/nr179/o7FGNMBZCenk5cXBxxcXGcc845NG7c\nOP/n48ePl2gft99+O5s2lXQeOJgyZQqjR48+05DLhc8H6kXEAyQAqap6lTvn91wgFtgOXK+q+91t\nHwdGAjnAn/PmABeR7jiTL4XiTP70oKqqO3vgTJy5uNOBPxY1q19ZaNWqFQDJycnUr1/fF4cwxlQi\nkZGRJCYmAvD0008TFhbGI488UmAbVUVVCQgo+u/36dOn+zzO8lYeLZUHgQ1eP48BPlfV1jhza48B\nEJH2OLMAdgAuBya5CQmc+a7vAlq7r8vd8pHAflVtBUzAmT3PJ7yTijHGFCc5OZn27dtz00030aFD\nB3bt2sWoUaOIj4+nQ4cOjB07Nn/bPn36kJiYSHZ2NhEREYwZM4YuXbpw/vnns2fPnhIf85133qFT\np0507NiRJ554AoDs7GxuueWW/PKJEycCMGHCBNq3b0/nzp25+eYiJ0k9Kz5tqYhIDHAlMA54yC0e\nAvR3l2cAXwF/dcvnqOoxYJuIJAM9RGQ7EK6qy919zgSG4swHPgRnWlKA+cCrIiLqg4GP2NhYAgIC\nLKkYUwGNHj06v9VQVuLi4njppZfOqO7GjRuZOXMm8fHxADz33HPUq1eP7OxsLrroIoYNG0b79u0L\n1MnIyKBfv34899xzPPTQQ0ybNo0xY8ac9lgpKSn87W9/IyEhgTp16nDxxRfz4YcfEh0dTVpaGklJ\nSQAcOHAAgOeff54dO3YQFBSUX1aWfN1SeQl4DMj1Kmugqrvc5d+ABu5yY+BXr+1S3LLG7nLh8gJ1\nVDUbyAAiCwchIqNEJEFEEs50TCQoKIhmzZpZUjHGnFbLli3zEwrAf/7zH7p160a3bt3YsGED69ev\nP6lOaGgogwYNAqB79+5s3769RMdasWIFAwYMICoqisDAQG688Ua++eYbWrVqxaZNm/jzn//M0qVL\nqVOnDgAdOnTg5ptvZvbs2Wf8BcdT8VlLRUSuAvao6ioR6V/UNu64iM9vp1LVycBkgPj4+DM+XqtW\nrSypGFMBnWmLwldq1aqVv7xlyxZefvllVq5cSUREBDfffHOR3wMJCgrKX/Z4PGRnZ59VDJGRkaxd\nu5YlS5bw2muvsWDBAiZPnszSpUv5+uuvWbRoEf/85z9Zu3YtHo/n9DssIV+2VC4Arna7r+YAA0Tk\nHWC3iDQEcN/zOg5TgSZe9WPcslR3uXB5gToiUgOogzNg7xOWVIwxpZWZmUnt2rUJDw9n165dLF26\ntEz337NnT7788kvS09PJzs5mzpw59OvXj71796KqXHfddYwdO5bVq1eTk5NDSkoKAwYM4Pnnnyct\nLY2srKwyjcdnLRVVfRx4HMBtqTyiqjeLyL+AW4Hn3PcP3CqLgH+LyItAI5wB+ZWqmiMimSLSC1gB\njABe8apzK/A9MAz4whfjKXlatWrF/v37SU9PJzLypF42Y4w5Sbdu3Wjfvj1t27alWbNmXHDBBWe1\nv6lTpzJ//vz8nxMSEnj22Wfp378/qsrgwYO58sorWb16NSNHjkRVERHGjx9PdnY2N954IwcPHiQ3\nN5dHHnmE2rVrn+0pFlAuc9R7JZWrRCQSmAc0BXbg3FK8z93uSeAOIBsYrapL3PJ4fr+leAnwgNt1\nFgLMAroC+4DhqvrzqWKJj4/XM52ka9GiRQwZMoTly5fTs2fPM9qHMaZsbNiwgXbt2vk7jCqpqGsr\nIqtUNb6YKvnK5YGSqvoVzl1eqGo6MLCY7cbh3ClWuDwB6FhE+VHgujIM9ZRat24NOLcMWlIxxpiT\n2TfqS6F58+aICFu2bPF3KMYYUyFZUimFkJAQoqKi+O233/wdijHGVEiWVEopLCyMw4cP+zsMY4yp\nkCyplJIlFWOMKZ4llVIKCwvj0KFD/g7DGGMqJEsqpVSrVi1LKsaYMnn0PcC0adOKHae9+eabWbhw\nYVmFXC5sjvpSCgsLY/fu3f4OwxjjZyV59H1JTJs2jW7dunHOOeeUdYh+YS2VUrIxFWPM6cyYMYMe\nPXoQFxfHfffdR25ubpGPop87dy6JiYn88Y9/LHELJzc3l4ceeoiOHTvSqVOn/G/Xp6am0qdPH+Li\n4ujYsSPLli0r9vH3vmQtlVKyMRVjKqj+/U8uu+oqyGs9lHb9V1+dURg//fQT77//PsuWLaNGjRqM\nGjWKOXPm0LJly5MeRR8REcErr7zCq6++SlxcXIn2/+6777JhwwbWrFnD3r17Oe+88+jbty/vvPMO\ngwcP5q9//Ss5OTkcOXKEVatWFfn4e1+ylkop2ZiKMeZUPvvsM3744Qfi4+OJi4vj66+/ZuvWrcU+\nir60vv32W2644QY8Hg/nnHMOffr0ISEhgfPOO48pU6bwzDPP8NNPPxEWFlZmxywNa6mUUlhYGFlZ\nWeTm5hY7Ragxxg9O17I42/UlpKrccccdPPvssyetK+pR9GVlwIABfPXVVyxevJgRI0bw2GOPcdNN\nN/n0mEWxT8VSCgsLAyjzx0UbY6qGiy++mHnz5pGWlgY4d4n98ssvRT6KHqB27docPHiwxPu/8MIL\nmTNnDrm5uezevZvvvvuO+Ph4duzYwTnnnMOoUaO4/fbb+fHHH4s9pi9ZS6WU8ibfOXToUH6CMcaY\nPJ06deIf//gHF198Mbm5uQQGBvLGG2/g8XhOehQ9wO23386dd95JaGgoK1euLDBZF8Cdd97Jn/70\nJ8B5/uDXX3/N8uXL6dy5MyLCiy++SP369Zk2bRovvvgigYGB1K5dm1mzZvHrr78WeUxfKpdH31ck\nZ/Poe4BZs2YxYsQItmzZQqtWrcowMmNMadij733nbB59b91fpZTXOrHBemOMOZkllVLKSyr2XRVj\njDmZz5KKiISIyEoRWSMi60TkGbf8aRFJFZFE93WFV53HRSRZRDaJyGVe5d1FJMldN1FExC0PFpG5\nbvkKEYn11fnk8R5TMcb4V3Xrvi8PZ3tNfdlSOQYMUNUuQBxwuTvPPMAEVY1zXx8BiEh7YDjQAbgc\nmCQiHnf714G7cOatb+2uBxgJ7FfVVsAEwOejUNb9ZUzFEBISQnp6uiWWMqSqpKenExIScsb78Nnd\nX+r8pvM+eQPd16l++0OAOap6DNgmIslADxHZDoSr6nIAEZkJDMWZq34I8LRbfz7wqoiI+vBfmSUV\nYyqGmJgYUlJS2Lt3r79DqVJCQkKIiYk54/o+vaXYbWmsAloBr6nqChEZBDwgIiOABOBhVd0PNAaW\ne1VPcctOuMuFy3HffwVQ1WwRyQAigbRCcYwCRgE0bdr0rM7JkooxFUNgYCDNmzf3dximEJ8O1Ktq\njqrGATE4rY6OOF1ZLXC6xHYBL/gyBjeOyaoar6rx0dHRZ7WvvDEVG6g3xpiTlcvdX6p6APgSuFxV\nd7vJJhd4C+jhbpYKNPGqFuOWpbrLhcsL1BGRGkAdIN1X5wEQGhqKiFhLxRhjiuDLu7+iRSTCXQ4F\nLgE2ikhDr82uAX5ylxcBw907uprjDMivVNVdQKaI9HLv+hoBfOBV51Z3eRjwhS/HUwACAgLsoZLG\nGFMMX46pNARmuOMqAcA8Vf1QRGaJSBzOoP124G4AVV0nIvOA9UA2cL+q5rj7ug94GwjFGaBf4pZP\nBWa5g/r7cO4e8zl7/L0xxhTNl3d/rQW6FlF+yynqjAPGFVGeAHQsovwocN3ZRVp6tWrVsjEVY4wp\ngn2j/gxYS8UYY4pmSeUMWFIxxpiiWVI5A5ZUjDGmaJZUSmrtWhgzBg4etDEVY4wphiWVktq6FcaP\nh02brKVijDHFsKRSUm3aOO8bN1pSMcaYYlhSKamWLSEgwFoqxhhzCpZUSio4GJo3h02bqFWrFseO\nHSM7O9vfURljTIViSaU02raFrVtt9kdjjCmGJZXSmDULVq6kYUPn8WWzZ8/2c0DGGFOxWFIpjbp1\nwePhuuuu48orr+SBBx5g6dKl/o7KGGMqDEsqpbFzJ9xzDzV+/JE5c+bQunVrnnzySX9HZYwxFYYl\nldLweODNN+H77wkLC+Oee+5h1apVrFu3zt+RGWNMhWBJpTTq14c6dWDTJgBuvPFGPB4Ps2bN8nNg\nxhhTMVhSKQ0RaNcONmwAoH79+gwaNIhZs2aRk5NzmsrGGFP1WVIprfbtYf36/B+vv/56du7cyXqv\nMmOMqa58OZ1wiIisFJE1IrJORJ5xy+uJyKcissV9r+tV53ERSRaRTSJymVd5dxFJctdNdKcVxp16\neK5bvkJEYn11PvnatYPsbHC/Ud+sWTMAdu/e7fNDG2NMRefLlsoxYICqdgHigMtFpBcwBvhcVVsD\nn7s/IyLtcaYD7gBcDkxypyIGeB24C2fe+tbueoCRwH5VbQVMAMb78Hwcf/kLpKWB+wXI+vXrA7Bn\nzx6fH9oYYyo6nyUVdeQ9ICvQfSkwBJjhls8AhrrLQ4A5qnpMVbcByUAPEWkIhKvqclVVYGahOnn7\nmg8MzGvF+IzHU+BHSyrGGPM7n46piIhHRBKBPcCnqroCaKCqu9xNfgMauMuNgV+9qqe4ZY3d5cLl\nBeqoajaQAUT64FQKGjkSJkwAICIigho1arBnzx5yc3P5+OOPcXKfMcZUPz5NKqqao6pxQAxOq6Nj\nofWK03rxKREZJSIJIpKwd+/es9/hjz/CJ58AEBAQQHR0NHv27GHp0qUMGjSI1atXn/0xjDGmEiqX\nu79U9QDwJc5YyG63Swv3Pa/fKBVo4lUtxi1LdZcLlxeoIyI1gDpAehHHn6yq8aoaHx0dffYn5HVb\nMThdYHv27GHLli0AHDhw4OyPYYwxlZAv7/6KFpEIdzkUuATYCCwCbnU3uxX4wF1eBAx37+hqjjMg\nv9LtKssUkV7ueMmIQnXy9jUM+ELLo++pfXvYsSP/DrC8pPLLL78AkJWV5fMQjDGmIqrhw303BGa4\nd3AFAPNU9UMR+R6YJyIjgR3A9QCquk5E5gHrgWzgflXN+0bhfcDbQCiwxH0BTAVmiUgysA/n7jHf\n69DBeV+/Hnr0oH79+iQnJ7Njxw7AkooxpvryWVJR1bVA1yLK04GBxdQZB4wrojwB6FhE+VHgurMO\ntrQ6dXIm7MrIAKBBgwbs2bPHkooxptrzZUul6mrZEn7+Of/H+vXrc/jwYTZu3AhYUjHGVF/2mJYy\nkPddlYMHDwKWVIwx1ZcllTP18stw3nnA70kljyUVY0x1ZUnlTOXmQkIC7NljScUYY1yWVM5UR/e+\ngZ9+sqRijDEuSypnqlMn5z0pibwvVHo8Hho0aMCRI0f8GJgxxviP3f11pho0gKgoSEqiZs2ahIWF\nUa9ePYKDg62lYoyptiypnCkRuPZaaNQIcAbrGzduTGZmpiUVY0y1ZUnlbLz5Zv7iAw88QFRUFJMm\nTbKkYoyptiypnC1VyMlh9OjRALz99tuWVIwx1ZYN1J+NlBSIjIR33skvqlmzpiUVY0y1ZUnlbDRs\nCMePO/OruCypGGOqM0sqZ8PjgS5dwGtSLksqxpjqzJLK2eraFRITnW/YY0nFGFO9WVI5W127OpN1\nbd0KWFIxxlRvllTO1gUXwL33Ol1hQGhoKEeOHCHXbbkYY0x1YrcUn622bWHSpPwfa9asCcDRo0fz\nl40xprrw5Rz1TUTkSxFZLyLrRORBt/xpEUkVkUT3dYVXncdFJFlENonIZV7l3UUkyV030Z2rHnc+\n+7lu+QoRifXV+ZxSdja489PnJRJ7/pcxpjryZfdXNvCwqrYHegH3i0h7d90EVY1zXx8BuOuGAx2A\ny4FJ7vz2AK8DdwGt3dflbvlIYL+qtgImAON9eD7Fu/9+6N4dVPOTio2rGGOqI58lFVXdpaqr3eWD\nwAag8SmqDAHmqOoxVd0GJAM9RKQhEK6qy1VVgZnAUK86M9zl+cDAvFZMuercGdLSICXFkooxplor\nl4F6t1uqK7DCLXpARNaKyDQRqeuWNQZ+9aqW4pY1dpcLlxeoo6rZQAYQWcTxR4lIgogk7N27t0zO\nqYCuXZ33H3+0pGKMqdZ8nlREJAxYAIxW1UycrqwWQBywC3jB1zGo6mRVjVfV+Ly5T8pU587OU4st\nqRhjqjmfJhURCcRJKLNV9T0AVd2tqjmqmgu8BfRwN08FmnhVj3HLUt3lwuUF6ohIDaAOkO6bszmF\nsDBo08aSijGm2vPl3V8CTAU2qOqLXuUNvTa7BvjJXV4EDHfv6GqOMyC/UlV3AZki0svd5wjgA686\nt7rLw4Av3HGX8vf3v8Odd1pSMcZUa778nsoFwC1AkogkumVPADeISBygwHbgbgBVXSci84D1OHeO\n3a+qOW69+4C3gVBgifsCJ2nNEpFkYB/O3WP+ceONANTctAmwpGKMqZ58llRU9VugqDuxPjpFnXHA\nuCLKE4CORZQfBa47izDLzokT8OOP1HYbSpZUjDHVkT2mpawcPAg9e1LnIydnWlIxxlRHllTKSr16\n0KwZwevXA5ZUjDHVkyWVstS1K561awFLKsaY6smSSlnq2hXZsoXokBB79pcxplqypFKWunUDVXoE\nBVlLxRhTLZUoqYhISxEJdpf7i8ifRSTCt6FVQhdcAIsWsa12bUsqxphqqaQtlQVAjoi0AibjfIv9\n3z6LqrKqWxcGDyYnLMySijGmWippUsl1H9h4DfCKqj4KNDxNnepp7VpuysqypGKMqZZKmlROiMgN\nOI9E+dAtC/RNSJXcBx/w5K+/knvgAAAvvPACY8aM8XNQxhhTPkqaVG4HzgfGqeo299lcs3wXViUW\nH08A4Fm7FlXljTfeYMGCBf6OyhhjykWJHtOiquuBPwO485/UVlX/zLJY0XXvDkCrjAxWrlxJcnIy\nERF2T4Mxpnoo6d1fX4lIuIjUA1YDb4nIi6erVy3Vr8/xhg2JB1580blEBw4cIDs7279xGWNMOShp\n91cdd4Kta4GZqtoTuNh3YVVugeefz3kizJ8/P79s//79fozIGGPKR0mTSg13HpTr+X2g3hRDJkzg\nkQsvJDc3N78sLS2NAwcOkJKScoqaxhhTuZU0qYwFlgJbVfUHEWkBbPFdWJVc06Z06tsXgPbt2wOQ\nnp7OY489xqBBg/wZmTHG+FRJB+rfBd71+vln4A++CqrSy81lxPbtrAPOHTyY9evXk56ezubNm0lN\nTT1tdWOMqaxKOlAfIyLvi8ge97VARGJOU6eJiHwpIutFZJ2IPOiW1xORT0Vki/te16vO4yKSLCKb\nROQyr/LuIpLkrpvoTiuMO/XwXLd8hYjEnslFKHMBAbRatoyXe/Zk1KhRgNP9lZqaSmZmJv6a8dgY\nY3ytpN1f03Hmg2/kvv7rlp1KNvCwqrYHegH3i0h7YAzwuaq2Bj53f8ZdNxzoAFwOTBIRj7uv14G7\ncOatb+2uBxgJ7FfVVsAEoMLc5izx8TTZvZsGDRoATlLZuXMnOTk59m17Y0yVVdKkEq2q01U12329\nDUSfqoKq7lLV1e7yQWAD0BgYAsxwN5sBDHWXhwBzVPWYqm4DkoEe7g0C4aq6XJ0/8WcWqpO3r/nA\nwLxWjN/Fx8P27dTMyiI4OJiff/45P5lkZmb6OThjjPGNkiaVdBG5WUQ87utmIL2kB3G7pboCK4AG\nqrrLXfUb0MBdbgz86lUtxS1r7C4XLi9Qx302WQYQWcTxR4lIgogk7N27t6Rhn534eOfYP/5IVFQU\na93JuwAyMjLKJwZjjClnJU0qd+DcTvwbsAsYBtxWkooiEobzlOPR7ndd8rktD58PMKjqZFWNV9X4\n6OhTNrDKTufO4PHAL78QGRlJUlJS/iprqRhjqqoSJRVV3aGqV6tqtKrWV9WhlODuLxEJxEkos1X1\nPbd4t9ulhfu+xy1PxXmkfp4YtyzVXS5cXqCOiNQA6lCKFpRPRUbC4cNw551ERkZy+PDh/FXWUjHG\nVFVnM/PjQ6da6Y5tTAU2qKr3I10W4TztGPf9A6/y4e4dXc1xBuRXul1lmSLSy93niEJ18vY1DPhC\nK9KtVcHBAERFRRUotqRijKmqSvQ9lWKcbkD8AuAWIElEEt2yJ4DngHkiMhLYgdOthqquE5F5wHqc\nO8fuV9Uct959wNtAKLDEfYGTtGaJSDKwD+fusYpj8WKYOJH6zZoVKLbuL2NMVXU2SeWULQJV/Zbi\nE8/AYuqMA8YVUZ4AdCyi/Chw3Wkj9ZfMTPjkE9rcdRcAMTExpKSkWEvFGFNlnTKpiMhBik4egtNq\nMKfSuTPCVXsYAAAgAElEQVQArY4cAaBt27akpKRYS8UYU2WdMqmoau3yCqRKOvdcCAqi6b59ADRt\n2pSwsDBrqRhjqqyzGag3pxMYCO3bU/+33wBo3Lgx4eHh1lIxxlRZllR8rXdvatSsCThJpU6dOtZS\nMcZUWZZUfO211whcsoTLLruMAQMGWEvFGFOlnc3dX6aEwsLC+PjjjwGspWKMqdKspeJrWVnQsye8\n/joA4eHhllSMMVWWJRVfq1kTduyAlSsBp6Vi3V/GmKrKkkp56NIF3KcUW/eXMaYqs6RSHjp3hnXr\nIDub8PBwDh8+TE5OzunrGWNMJWNJpTx07gzHjsHmzdSpUwew538ZY6omSyrloXt3uOQSOH6c8PBw\nwJKKMaZqsluKy0P79vDJJwDU2boVsMffG2OqJmuplKecnPyWiiUVY0xVZEmlvDz2GLRubWMqxpgq\nzZJKeYmKgm3biMjNBaylYoypmnyWVERkmojsEZGfvMqeFpFUEUl0X1d4rXtcRJJFZJOIXOZV3l1E\nktx1E90phXGnHZ7rlq8QkVhfnUuZcOdWaZiWhoiwZcsWPwdkjDFlz5ctlbeBy4son6Cqce7rIwAR\naY8zFXAHt84kEfG4278O3IUzZ31rr32OBParaitgAjDeVydSJtykUnvbNnr37s17773n54CMMabs\n+SypqOo3OPPGl8QQYI6qHlPVbUAy0ENEGgLhqrpcVRWYCQz1qjPDXZ4PDMxrxVRIDRtCZCSsXcuw\nYcNYu3attVaMMVWOP8ZUHhCRtW73WF23rDHwq9c2KW5ZY3e5cHmBOqqaDWQAkb4M/KyIwP33Q69e\nXHvttQAsWLDAz0EZY0zZKu+k8jrQAogDdgEvlMdBRWSUiCSISMLevXvL45BFe+YZGDmSpk2b0qNH\nD0sqxpgqp1yTiqruVtUcVc0F3gJ6uKtSgSZem8a4ZanucuHyAnVEpAZQB0gv5riTVTVeVeOjo6PL\n6nTOTHo67NlD//79Wbt2LU6vnjHGVA3lmlTcMZI81wB5d4YtAoa7d3Q1xxmQX6mqu4BMEenljpeM\nAD7wqnOruzwM+EIr+if0kSPQqBG89BKNGjXi+PHj7NtX0mEnY4yp+Hz2mBYR+Q/QH4gSkRTgH0B/\nEYkDFNgO3A2gqutEZB6wHsgG7lfVvMf43odzJ1kosMR9AUwFZolIMs4NAcN9dS5lJjQU4uPhiy9o\n9PDDAOzcuZPIyIo7FGSMMaXhs6SiqjcUUTz1FNuPA8YVUZ4AdCyi/Chw3dnE6BcXXQTPPUeTiAjA\nSSqdOnXyc1DGGFM27Bv15e2iiyAnh9hffgGcpGKMMVWFJZXy1rs3hIQQtXo1ALt27fJzQMYYU3Ys\nqZS30FCYNo0a995L3bp1raVijKlSbD4Vf7jBGW5q1KiRJRVjTJViLRV/UIWFCxkUEmLdX8aYKsVa\nKv4gAo8+yk1HjjDP4zn99sYYU0lYS8VfrrySDrt3c3DnTjZu3MjUqcXebW2MMZWGJRV/uf56ArOz\nuSI7m5EjR3LnnXdy6NAhf0dljDFnxZKKv/TqxeGoKIYDy5YtA7BH4RtjKj1LKv4SEMCBSy+lKxDk\nFm3evNmfERljzFmzpOJH2WPG0Axo4z6mxZKKMaays6TiRw3btKHluefyxBNP0LRpU0sqxphKz24p\n9qOgoCA2TZgAf/kL85o3t6RijKn0rKXib9HRsHkzQz0eNm3aZJN2GWMqNUsq/hYfD02a0Gf3bjIy\nMvDrdMfGGHOWLKn4mwhcey3NNm+mNjZYb4yp3CypVAR/+AOeEye4EksqxpjKzWdJRUSmicgeEfnJ\nq6yeiHwqIlvc97pe6x4XkWQR2SQil3mVdxeRJHfdRHeuetz57Oe65StEJNZX5+JzvXuTe9NNHAgJ\nYckSZ7bkEydO2PiKMabS8WVL5W3g8kJlY4DPVbU18Ln7MyLSHmeO+Q5unUkikvekxdeBu4DW7itv\nnyOB/araCpgAjPfZmfiax0PAO+/Q47HHmD9/PjNmzCA2NpZx406aXdkYYyo0nyUVVf0G2FeoeAgw\nw12eAQz1Kp+jqsdUdRuQDPQQkYZAuKouV+fP9pmF6uTtaz4wMK8VU1k9Onw4PerV47bbbmPnzp18\n/fXX/g7JGGNKpby/p9JAVfMmEPkNaOAuNwaWe22X4padcJcLl+fV+RVAVbNFJAOIBNIKH1RERgGj\nAJo2bVomJ1LmcnII69uXue3acXVmJpGRkSQlJfk7KmOMKRW/DdS7LY9yGTRQ1cmqGq+q8dHR0eVx\nyNLzeODqq4lNSmLtDz8wePBgdu/ebbcYG2MqlfJOKrvdLi3c9z1ueSrQxGu7GLcs1V0uXF6gjojU\nAOoA6T6LvDz84Q+QmQmffUYn93lg1loxxlQm5Z1UFgG3usu3Ah94lQ937+hqjjMgv9LtKssUkV7u\neMmIQnXy9jUM+EIr++1SAwdCeDgsWGBJxRhTKfnyluL/AN8DbUQkRURGAs8Bl4jIFuBi92dUdR0w\nD1gPfAzcr6o57q7uA6bgDN5vBZa45VOBSBFJBh7CvZOsUgsOhquvhv/+lwZRUURFRVlSMcZUKlLZ\n/7gvrfj4eE1ISPB3GMXbsAFCQqB5cwYMGMDhw4dZsWKFv6MyxlRzIrJKVeNPt519o76iadcOmjcH\noFOnTqxbt47c3Fw/B2WMMSVjSaUi2rYNBg9mYL16HD582LrAjDGVhiWViqhuXfjiCy7ZuBERYeHC\nhf6OyBhjSsSSSkUUEQG33Uboe+9xZXw877//vr8jMsaYErGkUlE9+CCcOMETdeqwZs0atm3b5u+I\njDHmtCypVFTnnguDB9Nj1SpCgHnz5vk7ImOMOS2bo74ie+wxPG3aMHDZMv72t79Rr1497rzzTir5\nczONMVWYtVQqsgsugOef598ffcSAAQMYNWoUbdu2ZenSpf6OzBhjimRJpaJTJXzZMhb//e/MmDGD\nY8eO8fjjj/s7KmOMKZJ1f1V02dkwahQ16tVjxA8/8PPPPzN27FgyMjKoU6eOv6MzxpgCrKVS0QUG\nwsSJsGYNjB9Pv379UFW+++47f0dmjDEnsaRSGQwdCn/8I4wdS6+ICAIDA21WSGNMhWRJpbKYOBFq\n1iT0r3+lx3nn8c033/g7ImOMOYkllcqifn3417/g0kvp17cvCQkJHD582N9RGWNMAZZUKpO77oJH\nHuHiSy8lOzubZ5991t8RGWNMAZZUKqH+O3cyr3dvxo8fzxtvvOHvcIwxJp9fkoqIbBeRJBFJFJEE\nt6yeiHwqIlvc97pe2z8uIskisklELvMq7+7uJ1lEJko1+aq5fPQRw1at4rY+fbj33nu58cYbycrK\n8ndYxhjj15bKRaoa5zWT2Bjgc1VtDXzu/oyItAeGAx2Ay4FJIuJx67wO3IUzp31rd33V969/ISEh\nTAOe+cc/+M9//sO4ceP8HZUxxlSo7q8hwAx3eQYw1Kt8jqoeU9VtOHPV9xCRhkC4qi5XZ07kmV51\nqrZGjeCll5Bvv+WpyEhuueUW/t//+39s3brV35EZY6o5fyUVBT4TkVUiMsota6Cqu9zl34AG7nJj\n4FevuiluWWN3uXD5SURklIgkiEjC3r17y+oc/OvWW+Gyy+DJJ3n+kUcICgri0Ucf9XdUxphqzl9J\npY+qxgGDgPtFpK/3SrfloWV1MFWdrKrxqhofHR1dVrv1LxHnuyuvvMI5HTvy0EMP8f7777NlyxZ/\nR2aMqcb8klRUNdV93wO8D/QAdrtdWrjve9zNU4EmXtVj3LJUd7lwefVx7rlOiyUggHvvuougoCAm\nTpzo76iMMdVYuScVEaklIrXzloFLgZ+ARcCt7ma3Ah+4y4uA4SISLCLNcQbkV7pdZZki0su962uE\nV53q5b33OGfgQEZdcw3Tp0/nwIED/o7IGFNN+aOl0gD4VkTWACuBxar6MfAccImIbAEudn9GVdcB\n84D1wMfA/aqa4+7rPmAKzuD9VmBJeZ5IhREbCzt28M9t2zh++DBTp071d0TGmGpKnOGL6iM+Pl4T\nEhL8HUbZe/ttuP12ljZowN3BwSRv3UqNGjazgTGmbIjIKq+vgBSrIt1SbM7GbbfBs89y2e7d3PPL\nL3zwQfXsCTTG+JcllarkySfJHTWKFmFh/P3JJ0lMTARgz549/OUvf+HVV1/l0KFDfg7SGFOVWfdX\nVZOTw5KlS7llxAj279tH7wsuYOvWrezevZvc3FwaNGjA/Pnz6dOnj78jNcZUIiXt/rKkUkVlLFtG\nxvDhvCNCWnAw9//1rxwCbv3f/2X9L78w6eWXufPOO52ZJXNz4cQJCA4u+QEOH4bduyEzEw4edPYB\n0L07hIXBzp2QnAxBQRAa6rxq1oQGDZxjGmMqFUsqxaguSYUNG6B/f9izp0Bx5kcfcf3LLxO9dCmz\nAA0KghMnEFVyIiLwfPwxhzt2ZPpNNzFo0yZa1q/vJI7MTDQjA/nqK+jYEV57Df70p5MOe2TZMkLP\nPx9efx3uu+/kuFavZnvdugRNn07D559HataEkBAnoQUHw3vvQbt28MEH8OqrBdcFB8Mzz0CTJrBi\nBXz0UcF1wcFw7bUQGQlbt0JSkpPAAgOd5BYYCHFxUKsW7NsHaWm/r8971akDHg+oOl8wNcYAJU8q\ndntQVdWundNa2LkTdu1yWhaHDhHesyeLFy/m5ZEj+duMGUQCB1XJEaGdKoHLl/PUHXfQYf16egPb\njhwhNyyMzQcOsG3fPlY9+CADR46E3btpeNtthDduTHTz5rz+1lssX7GChN696dy7Nx0jIkgGgoBO\nLVty+/DhtDjnHKYuXszosWOJP3GCm2rW5A8XXURoQACb1qwhJiqKBiEheIAt69cTsnEjcvw4tWrU\nICwwkMCcHPjrX8nKymL9pEnEz5x50mknR0fzXUYGDd99l0sXLz5pffbq1UxZsYJmH3zAoI8/Prn+\ne++xKyqKXitXEvjooxAYiAYGojVqEBAUBF9/TVazZswdPJirk5KoW7cuAQEBTgISgYULoXVrmD0b\nxo//vTwvQc2fz4q0NLLfeYcLvv/+5N/b3LnQsiXMmeNMylbYvHnO+tmz4bnnnBaiqvOemwuLFzvH\nnz7dScCF13/1FbRpA2+9BU8+Cd6xi8AXXzjrp0+HsWOdBOvxQI0azvuCBc7+330XXnrJKQPnGKow\naxY0b+6cx4QJBWMXceJu0cI5j5df/r08733mTKf+/PnwyisF64ITV/Pmzh8fr7128vopU5xb7N9/\n3/nDRsQ5x4AAJ9ZXXoFmzZw/SN5+2ynzXv8//wMxMc51ePfdgusDAuDRR6FhQ1i2DD7/HFq1cq5X\n69ZQu/bJv69qyJJKVebxOH/VN2lSsBh46O23WX7PPTzxxBNccMEFXHzxxVxyySWcGD2aJk2acOfS\npYyfOpV58+YB0LlzZ/rddBMLZs5k2hdfnHSo0NBQHnjsMfqGhDBz5kwSEhJ47G9/Izw8nEmTJvEv\nr6coDx06lKFDh/Lss8/y5Gef4fF42LdvH2zeTMtLLuGyyy7jzTffJCcnh5CQEI4ePQpAly5daPDn\nP/Pjjz+S9wy3ICDYfYUAu6+5hhNAJHBuSAihNWpw9NAhgoBA4JfBg9mUmsq5wDtuWbAIjaKjyUxP\n5+1rr2UfcG3DhjwzZAgxDRrw8X//S/ru3VzUpw/Zv/zC3XfcQd3lywkFamdlcdFFF1HD42FnaioN\nRQhSZVt6OnUiIggJDqZmaCh79u7FExBAzr59XHnllfROT+fVzp0ByDp8mFatW1Mj78Mb0NBQdgEb\nNmwgOjqaTp06kZOby4kTJwhRZVdWFpGxsQQHB//+gSfitOwAGjcms3t3jh07RlT9+ojH46wPCwMg\nJzaWX7t3Jzoqilqhob8nhbwPxsaN4cILnUSUnQ05Oc573v49HqdLM8f9yljh5BkU5LT68n7O6xEJ\ncO8NqlHD6Q7NK897904wedsW1ZuSkwPHjxdYf/DQIbLT06kbG+t05x46hObmIqrO9nnnApCe7rRk\n85Jt3vojR5z1yclOAs1bn/caNcpJKgkJ8NRTBWNq2BC+++73pDhtmtNFvHu3c9zwcPi//3O6gOfP\nd/4ACA93Xjk5cPSok9Rq1oQlS5x9nXOOs9+892bNnGuf190cUPHutbLuL5NvxYoV5OTk0KtXLwIC\nAjh+/DiLFy+ma9euxMbGApCRkUFKSgpRUVFkZ2ezefNmVq9ezdVXX03r1q0ByMnJ4fjx44SGhgJw\n5MgR3nzzTbKysoiLi2PQoEGICL/88gv9+vUjJCSE999/n6SkJJ577jlWr17NsGHDmDJlCuHh4WzY\nsIElS5awePFisrKyiImJ4f7776dOnTps3ryZLVu2EBAQQN26dalbty4dOnQgJCSE5557DlXl0ksv\npWnTpnz++ed89tln/OlPf6J///58+eWXHD58mO3bt5OYmEibNm3o1q0bHo+HZ599lp9++gmAkJAQ\n4uLiWL58OQDBwcH8+9//Jjw8nGuuuYa2bduSnZ1NYmIiPXr0oHbt2nz++ef517VmzZr5893ExMSQ\nlpZG165d+d6rpdKmTRtatGhBZmYmffv25ZNPPmHVqlXExMSQkpJCv379+OGHHzh27BgNGjRg586d\nhIWFcf/995Oenk5qqvOEop49e1K/fn2+/PJLFixYQG5uLh07dmTKlCn07NkTgEWLFvHggw+yfft2\nGjVqxOLFi4mLiyvwb2HDhg1Mnz6dBx54gCZNmvDzzz/z3Xff0axZM/r2LfCovmJlZWUxd+5c3nvv\nPW644QZuvPFGAI4fP05SUhLdunWjuCmQtmzZwvPPP89DDz1EcHAwjz76KE2aNOGWW26he/fuAKhq\nfv1p06YxcuRIYmJimD17Ni1atGDs2LF88MEHvPHGGwwZMoS0tDSio6NJTU3l008/JSQkBBHh2LFj\nDBo0iPr16+fvd8uWLXzzzTc0bNiQXr16ERkZyZo1a0hMTGTEiBFkZGSw7PPPuaRFCwJ//hndtIm1\n8+fz0913c9Pddztdt9OnO8kgbxwxI8NpSYWFwQsvOC01t2sZj8dJ2D//DNHRTsL65z9/T9p59u2D\nunXh4YfhxRed5Jv3x0iNGk7PRO3aMG6c0xKrWRNq1UJr1uTDo0dp9/bbtGrVqkS/v8JK2v2Fqlar\nV/fu3dVUHFlZWXr8+PH8n3Nzc3XTpk2am5vrx6hUs7Oz9csvv9R//OMfumrVKs3OztYZM2bo7Nmz\nddeuXfnbLVy4UAENCQnRp556SsPCwjQ8PFwnTJign3zyib722ms6atQofffdd3XMmDEaEBCgkyZN\n0v379+uIESN01qxZ+umnn2qbNm20U6dOet5556mIaOvWrXXq1KmanZ2tDz/8sAYEBOhNN92kTzzx\nhA4fPlxfeeUVHTJkiAJat25d7d69u3bq1ElFRAGNjIzURx99VN966y1t3ry51qpVS99880198MEH\nFdAuXbroW2+9pY0bN1ZAa9asqb1799bHH39cx44dq2FhYQpoeHi4dujQIe8BrwrorbfeqsOHD9eu\nXbvqueeeq/fdd59OnTpVx4wZo9OnT9fvvvtO33zzTY2JiVFAa9WqpSKi06ZN0/379+uAAQMU0PPP\nP18//vhjzcnJ0aSkJP3uu+80KSlJJ0+erBEREfnnERMTo2FhYRocHKxBQUG6cOFCHTZsmIaGhmrv\n3r21X79+KiLav39/bdasWX6cHo9HW7VqpYDWqVNHAY2IiNCAgIAC5wNocHCwXnnllXrLLbdoixYt\nCqwLCgrSa665RoOCghTQSZMm6YUXXqiAtmzZUt99912dOnVq/vZjx47V3NxcXbhwodarV08vvfRS\nHTZsmJ577rnaqVMnveKKK/Tpp5/WrVu3alZWli764AM9cOCApqen65AhQ7R79+56xRVX6LS33tKD\nW7eqJiZq5rvv6rE331R1/19see01ndW6tX5xwQW68/bbVR99VPUvf1E9dsz5hzl7tuoNN6hefbXq\nwIGa0qSJ/g/olClTzvj/BJCgJfiM9fuHfHm/LKmYsrZw4UJduXKlqqqmpqbq3r17i9324MGDp91f\nZmamZmdnl6heWlpagQSclpamO3bsKFC2c+fOAolh5MiReuTIkfx4x48fr6NHj85PaID27NlTv/nm\nG73qqqu0b9+++vLLL2tiYqI+9NBDCmjDhg31iiuu0MGDB2tISIgCJ31Yd+vWTb/44gs9fPiw9u/f\nXwEVEfV4PDp69Oj8hFarVq2TPuS7dOmin376qcbGxmpkZKQmJiZqWlqadu7cOf9YI0aM0D59+uiF\nF16o9913n2ZlZWl6erpOmzZNJ0yYoImJiXrkyBF98skn9e6779YXXnhB77nnHn3qqac0KSlJ169f\nr+vWrdPVq1frvffeq506ddKGDRvqVVddpa+99ppu3LhRv/76a73nnnu0Zs2aOnTo0PyECOjjjz+u\n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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x116cb1cf8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "# Plot loss (MSE) over time\n",
    "plt.plot(loss_vec, 'k-', label='Train Loss')\n",
    "plt.plot(test_loss, 'r--', label='Test Loss')\n",
    "plt.title('Loss (MSE) per Generation')\n",
    "plt.legend(loc='upper right')\n",
    "plt.xlabel('Generation')\n",
    "plt.ylabel('Loss')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python [default]",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
